package engine;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.SwingWorker;
import ui.UserInterface;

import model_booleen.*;
        
public class SimilarityCalculator extends SwingWorker<ArrayList<ResultEntry>, Integer> {

    public static enum SimilarityModel {

        VECTORIEL, BOOL_ETENDU, BOOL_SIMPLE
    };
    private SimilarityModel model;
    private Request request;
    private ArrayList<Document> documents;
    private ArrayList<ResultEntry> results;
    private String rootPath;
    private UserInterface guiToUpdate;

    public SimilarityCalculator(SimilarityModel model,
            Request request,
            ArrayList<Document> documents,
            String rootPath) {
        this.model = model;
        this.request = request;
        this.documents = documents;
        this.rootPath = rootPath;
    }

    public double modeleVectoriel(Request r, Document d) {
        Double result = 0.;

        HashMap<String, Double> docWieghts = d.getWieghts();

        Double wR, wQ;
        Double sumR = 0., sumQ = 0.;
        for (Map.Entry<String, Double> entry : r.getWieghts().entrySet()) {
            wR = entry.getValue();
            wQ = docWieghts.get(entry.getKey());

            sumR += wR;
            sumQ += wQ;

            result += wR * wQ;
        }

        result = (sumR * sumQ == 0.) ? 0. : result / (sumR * sumQ);

        return result;
    }

    public double modeleBoolSimple(Request r, Document d) {

        RechercheBooleanSimple.buildQuery(r.getRequest());
        return RechercheBooleanSimple.calculus(d.getWieghts());
    }

    public double modeleBoolEtendu(Request r, Document d) {

        RegleRecherche.buildQuery(r.getRequest());
        return RegleRecherche.calculus(d.getWieghts());
    }

    @Override
    protected ArrayList<ResultEntry> doInBackground() throws Exception {
        results = new ArrayList<ResultEntry>();

        int compteur = 0, progress;
        double score = 0;

        for (Document currentDocument : this.documents) {
            compteur++;

            switch (model) {
                case VECTORIEL:
                    score = modeleVectoriel(this.request, currentDocument);
                    break;
                case BOOL_ETENDU:
                    score = modeleBoolEtendu(this.request, currentDocument);
                    break;
                case BOOL_SIMPLE:
                    score = modeleBoolSimple(this.request, currentDocument);
                    break;
            }

            results.add(new ResultEntry(currentDocument.getFilePath(), score, this.rootPath));

            progress = (int) ((double) compteur * 100 / (double) this.documents.size());
            publish(progress);
        }

        return results;
    }

    @Override
    protected void process(List<Integer> values) {
        for (Integer val : values) {
            guiToUpdate.updateProgressBarSimilarity(val);
        }
    }

    @Override
    protected void done() {
        guiToUpdate.similarityCalculated();
    }

    public void setGuiToUpdate(UserInterface guiToUpdate) {
        this.guiToUpdate = guiToUpdate;
    }
}
